home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #2 / Monster Media No. 2 (Monster Media)(1994).ISO / prog_gen / guslib.zip / GUSLIB.ASM < prev    next >
Assembly Source File  |  1994-08-26  |  23KB  |  979 lines

  1.             ideal
  2.             model large ; Replace this w/ whatever model your using
  3.             p286        ; This code was   written  for 286+ machines
  4.             jumps       ; Allows far conditional jumps in 286 code
  5.  
  6.             assume     ds:gus_data,cs:gus
  7.  
  8.             public     guslib
  9.  
  10. ; Our variables are stored  in our own segment for portability...
  11.  
  12. segment              gus_data private
  13. gus_string           db    'ULTRASND=',0
  14.  
  15. base_port            dw    ?
  16. gf1_page             dw    ?
  17. gf1_register         dw    ?
  18. gf1_data_low         dw    ?
  19. gf1_data_high        dw    ?
  20. irq_status           dw    ?
  21. timer_control        dw    ?
  22. timer_data           dw    ?
  23. dram                 dw    ?
  24. mixer                dw    ?
  25. irq_dma_control      dw    ?
  26. register_controls    dw    ?
  27. mixer_controls       dw    ?
  28.  
  29. play_back_dma        db    ?
  30. play_back_dma_mask   db    ?
  31. gf1_irq              db    ?
  32. gf1_irq_mask         db    ?
  33. midi_irq             db    ?
  34. midi_irq_mask        db    ?
  35.  
  36. irq_control          db    8,15,12,11,7,3,5,2,0
  37. dma_control          db    6,7,6,5,3,1,0
  38. dma_channels         db    7 dup (00h)
  39.                             db    0ah,0ch,02h,03h,0bh,83h,0ah
  40.                             db    7 dup (00h)
  41.                             db    0ah,0ch,06h,07h,0bh,82h,0ah
  42.                             db    7 dup (00h)
  43.                             db    0d4h,0d8h,0c4h,0c6h,0d6h,8bh,0d4h
  44.                             db    0d4h,0d8h,0c8h,0cah,0d6h,89h,0d4h
  45.                             db    0d4h,0d8h,0cch,0ceh,0d6h,8ah,0d4h
  46.  
  47. initialization       db    ?
  48. voice                db    00h
  49. max_voices           db    14h
  50. divisor              dw    0000h
  51. d1                   db    ?
  52. d2                   db    ?
  53.  
  54. old_ISR1             dd    ?
  55. old_ISR2             dd    ?
  56. old_flags            dw    ?
  57. irq_source           db    ?
  58. irq_voice            db    ?
  59. old_voice            db    ?
  60.  
  61. dma_send             dw    0000h
  62. dma_pos_high         db    00h
  63. dma_pos_low          dw    0000h
  64. dma_size_high        db    00h
  65. dma_size_low         dw    0000h
  66. dma_busy             db    00h
  67. dma_wait             db    00h
  68. dram_addr            dw    0000h
  69.  
  70.  
  71. gus_functions        dw    offset init_gus
  72.                             dw    offset deinit_gus
  73.                             dw    offset poke
  74.                             dw    offset peek
  75.                             dw    offset set_active
  76.                             dw    offset download_sound
  77.                             dw    offset dma_status
  78.                             dw    offset set_volume
  79.                             dw    offset set_freq
  80.                             dw    offset set_loop
  81.                             dw    offset set_start
  82.                             dw    offset set_end
  83.                             dw    offset play_voice
  84.                             dw    offset voice_status
  85.                             dw    offset stop_voice
  86.                             dw    offset read_8bit_reg
  87.                             dw    offset write_8bit_reg
  88.                             dw    offset read_16bit_reg
  89.                             dw    offset write_16bit_reg
  90.  
  91. lc                   db    '0'
  92. pos                  dw    3840
  93. ends        gus_data
  94.  
  95. segment  gus      public
  96. proc     value16  near
  97.             push     ax bx di es
  98.             mov      bx,0b800h
  99.             mov      es,bx
  100.             mov      al,[lc]
  101.             mov      di,[pos]
  102.             mov      [es:di],al
  103.             inc      [lc]
  104.             cmp      [lc],'9'+1
  105.             jnz      nu
  106.             mov      [lc],'0'
  107. nu:      add      [pos],2
  108.             cmp      [pos],4000
  109.             jnz      nu2
  110.             mov      [pos],3840
  111. nu2:     pop      es di bx ax
  112.             ret
  113. endp     value16
  114.  
  115.  
  116. proc     guslib   far
  117.             cmp      bx,12h
  118.             jnc      No_Func
  119.             push     ds
  120.             push     ax
  121.             mov      ax,gus_data
  122.             mov      ds,ax
  123.             pop      ax
  124.             shl      bx,1
  125.             add      bx,offset gus_functions
  126.             call     [word ptr ds:bx]
  127.             pop      ds
  128. No_Func: ret
  129. endp     guslib
  130.  
  131. proc     delay    near
  132.             push     cx dx ax
  133.             mov      cx,7
  134.             mov      dx,[base_port]
  135. d_lp1:   in       al,dx
  136.             loop     d_lp1
  137.             pop      ax dx cx
  138.             ret
  139. endp     delay
  140.  
  141. proc     read_8bit_reg  near
  142.             push     dx
  143.             pushf
  144.             cli
  145.             mov      dx,[gf1_register]
  146.             cmp      al,0fh
  147.             jnc      no_spc
  148.             add      al,80h
  149. no_spc:  out      dx,al
  150.             add      dx,2
  151.             in       al,dx
  152.             popf
  153.             pop      dx
  154.             ret
  155. endp     read_8bit_reg
  156.  
  157. proc     read_16bit_reg near
  158.             push     dx
  159.             pushf
  160.             cli
  161.             mov      dx,[gf1_register]
  162.             cmp      al,0fh
  163.             jnc      no_spc2
  164.             add      al,80h
  165. no_spc2: out      dx,al
  166.             inc      dx
  167.             in       ax,dx
  168.             popf
  169.             pop      dx
  170.             ret
  171. endp     read_16bit_reg
  172.  
  173. proc     write_8bit_reg near
  174.             push     dx
  175.             push     ax
  176.             pushf
  177.             cli
  178.             mov      dx,[gf1_register]
  179.             out      dx,al
  180.             add      dx,2
  181.             mov      al,ah
  182.             out      dx,al
  183.             call     delay
  184.             out      dx,al
  185.             popf
  186.             pop      ax
  187.             pop      dx
  188.             ret
  189. endp     write_8bit_reg
  190.  
  191. proc     write_16bit_reg near
  192.             push     dx
  193.             push     ax
  194.             pushf
  195.             cli
  196.             mov      dx,[gf1_register]
  197.             out      dx,al
  198.             inc      dx
  199.             mov      ax,cx
  200.             out      dx,ax
  201.             call     delay
  202.             out      dx,ax
  203.             popf
  204.             pop      ax
  205.             pop      dx
  206.             ret
  207. endp     write_16bit_reg
  208.  
  209. proc     poke     near ; si=high di=low al=value
  210.             pushf
  211.             push     dx
  212.             push     ax
  213.             cli
  214.             mov      dx,[gf1_register]
  215.             mov      al,43h
  216.             out      dx,al
  217.             inc      dx
  218.             mov      ax,di
  219.             out      dx,ax
  220.             dec      dx
  221.             mov      al,44h
  222.             out      dx,al
  223.             inc      dx
  224.             inc      dx
  225.             mov      ax,si
  226.             out      dx,al
  227.             add      dx,2
  228.             pop      ax
  229.             out      dx,al
  230.             call     delay
  231.             out      dx,al
  232.             pop      dx
  233.             popf
  234.             ret
  235. endp     poke
  236.  
  237. proc     peek     near ; ah=voice si=high di=low al=return value
  238.             push     dx
  239.             mov      dx,[gf1_register]
  240.             mov      al,43h
  241.             out      dx,al
  242.             inc      dx
  243.             mov      ax,di
  244.             out      dx,ax
  245.             dec      dx
  246.             mov      al,44h
  247.             out      dx,al
  248.             inc      dx
  249.             mov      ax,si
  250.             out      dx,al
  251.             add      dx,3
  252.             xor      ax,ax
  253.             in       al,dx
  254.             pop      dx
  255.             ret
  256. endp     peek
  257.  
  258. proc     init_gus near
  259.             mov      [initialization],00h    ; Don't need to deinit yet
  260.             push     es
  261.             mov      ah,51h                  ; Get the current PSP segment
  262.             int      21h
  263.             mov      es,bx
  264.             mov      ax,[es:002ch]           ; Find the environment strings
  265.             mov      es,ax
  266.             mov      si,offset gus_string
  267.             mov      di,0                    ; Find the 'ULTRASND=' string
  268. env_lp1: mov      al,[es:di]
  269.             inc      di
  270.             cmp      al,0
  271.             jnz      env_lp2
  272.             mov      al,[es:di+1]
  273.             cmp      al,0
  274.             jz       env_err
  275. rst_env: mov      si,offset gus_string
  276.             jmp      env_lp1
  277. env_lp2: mov      ah,[si]
  278.             cmp      ah,0
  279.             jz       env_ok
  280.             cmp      al,ah
  281.             jnz      rst_env
  282.             inc      si
  283.             jmp      env_lp1
  284. env_err: mov      ax,1                    ; String not found - Return  code 1
  285.             jmp      init_done
  286. env_ok:  xor      ax,ax                   ; Found string - Process variable
  287.             mov      al,[es:di]
  288.             sub      al,'0'
  289.             rol      ax,4
  290.             add      ax,200h
  291.             mov      [base_port],ax          ; Base Port   (2x0h)
  292.             add      di,3
  293.             mov      al,[es:di]
  294.             sub      al,'0'
  295.             mov      [play_back_dma],al      ; Play back DMA Channel
  296.             add      di,4
  297.             mov      al,[es:di]
  298.             sub      al,'0'
  299.             mov      [gf1_irq],al            ; GF1 (Channel 1) Irq
  300.             add      di,2
  301.             mov      al,[es:di]
  302.             sub      al,'0'
  303.             mov      [midi_irq],al           ; MIDI (Channel 2) Irq
  304.             mov      bx,[base_port]          ; Set up I/O port address
  305.             mov      [mixer],bx              ; Mix Control Register (2x0h)
  306.             add      bx,0bh
  307.             mov      [irq_dma_control],bx    ; IRQ/DMA Control Register
  308.             add      bx,04h
  309.             mov      [register_controls],bx  ;   Register Controls
  310.             add      bx,0f3h
  311.             mov      [gf1_page],bx           ; GF1 Page Selector
  312.             inc      bx
  313.             mov      [gf1_register],bx       ; GF1/Global Register Selector
  314.             inc      bx
  315.             mov      [gf1_data_low],bx       ; GF1/Global Data Low Byte
  316.             inc      bx
  317.             mov      [gf1_data_high],bx      ; GF1/Global Data High Byte
  318.             inc      bx
  319.             mov      [mixer_controls],bx     ; Mixer Conrols
  320.             sub      bx,100h
  321.             mov      [irq_status],bx         ; Irq Status Register
  322.             add      bx,2
  323.             mov      [timer_control],bx      ; Timer Control Register
  324.             inc      bx
  325.             mov      [timer_data],bx         ; Timer Data
  326.             add      bx,0feh
  327.             mov      [dram],bx               ; Direct DRAM I/O Register
  328.  
  329. ; Environmental Variables are loaded...  Procede w/ reseting the GUS
  330.  
  331.             mov      ax,064ch                ; Write 06h   to Reset port (4ch)
  332.             call     write_8bit_reg
  333.             mov      ax,074ch                ; Done w/ reset, now write 07h
  334.             call     write_8bit_reg
  335.             mov      al,4ch                  ; Read the reset port
  336.             call     read_8bit_reg
  337.             mov      bl,al
  338.             mov      ax,4                    ; If it isn't 07h, then we've
  339.             cmp      bl,07h                  ; got a problem...
  340.             jnz      init_done
  341.  
  342. ; Now, make sure the on board memory is there.  This ensures that
  343. ; we acually have an ultrasound.
  344.  
  345.             mov      al,33h
  346.             mov      si,0
  347.             mov      di,0
  348.             call     poke
  349.             mov      al,55h
  350.             mov      di,2
  351.             call     poke
  352.             mov      di,0
  353.             call     peek
  354.             cmp      al,33h
  355.             jnz      bad_dram
  356.             mov      di,2
  357.             call     peek
  358.             cmp      al,55h
  359.             jnz      bad_dram
  360.  
  361. ; Now set up the on-board IRQs...
  362.  
  363.             mov      dx,[mixer]
  364.             mov      al,4fh
  365.             out      dx,al
  366.             xor      cx,cx
  367.             mov      cl,[byte irq_control]
  368.             mov      si,1
  369.             mov      ah,[gf1_irq]
  370. rst_lp1: mov      al,[byte  irq_control+si]
  371.             cmp      ah,al
  372.             jz       rst_dn1
  373.             inc      si
  374.             loop     rst_lp1
  375.             jmp      bad_irq
  376. rst_dn1: dec      cx
  377.             mov      [gf1_irq_mask],cl
  378.             xor      cx,cx
  379.             mov      cl,[byte irq_control]
  380.             mov      si,1
  381.             mov      ah,[midi_irq]
  382. rst_lp2: mov      al,[byte  irq_control+si]
  383.             cmp      ah,al
  384.             jz       rst_dn2
  385.             inc      si
  386.             loop     rst_lp2
  387.             jmp      bad_irq
  388. rst_dn2: dec      cx
  389.             mov      [midi_irq_mask],cl
  390.             mov      dx,[irq_dma_control]
  391.             mov      bl,0
  392.             mov      al,[gf1_irq_mask]
  393.             mov      ah,[midi_irq_mask]
  394.             cmp      ah,al
  395.             jnz      ct_msk1
  396.             mov      ah,0
  397.             mov      bl,40h
  398. ct_msk1: rol      ah,3
  399.             or       al,ah
  400.             or       al,bl
  401.             out      dx,al
  402.             mov      dx,[mixer]
  403.             mov      al,0fh
  404.             out      dx,al
  405.             xor      cx,cx
  406.             mov      cl,[byte dma_control]
  407.             mov      si,1
  408.             mov      ah,[play_back_dma]
  409. rst_lp3: mov      al,[byte  dma_control+si]
  410.             cmp      ah,al
  411.             jz       rst_dn3
  412.             inc      si
  413.             loop     rst_lp3
  414.             jmp      bad_dma
  415. rst_dn3: dec      cx
  416.             mov      al,40h
  417.             or       al,cl
  418.             mov      dx,[irq_dma_control]
  419.             out      dx,al
  420.             mov      al,[play_back_dma]
  421.             and      al,3
  422.             mov      [play_back_dma_mask],al
  423.  
  424. ; Set up IRQs and ISRs.  From this point, deinitialization is a MUST!
  425.  
  426.             pushf
  427.             cli
  428.             mov      ah,35h
  429.             mov      al,[gf1_irq]
  430.             add      al,8
  431.             int      21h
  432.             mov      [word old_ISR1],bx
  433.             mov      [word old_ISR1+2],es
  434.             mov      ah,35h
  435.             mov      al,[midi_irq]
  436.             add      al,8
  437.             int      21h
  438.             mov      [word old_ISR2],bx
  439.             mov      [word old_ISR2+2],es
  440.             mov      ah,25h
  441.             mov      al,[gf1_irq]
  442.             add      al,8
  443.             push     ds
  444.             mov      dx,offset gf1_ISR
  445.             mov      bx,seg gf1_ISR
  446.             mov      ds,bx
  447.             int      21h
  448.             pop      ds
  449.             mov      ah,25h
  450.             mov      al,[midi_irq]
  451.             add      al,8
  452.             push     ds
  453.             mov      dx,offset midi_ISR      ; Like we're using it here?!?
  454.             mov      bx,seg midi_ISR
  455.             mov      ds,bx
  456.             int      21h
  457.             pop      ds
  458.             in       al,0a1h
  459.             mov      ah,al
  460.             in       al,21h
  461.             mov      [old_flags],ax
  462.             mov      bx,1
  463.             mov      dx,1
  464.             mov      cl,[gf1_irq]
  465.             shl      bx,cl
  466.             mov      cl,[midi_irq]
  467.             shl      dx,cl
  468.             or       bx,dx
  469.             not      bx
  470.             and      ax,bx
  471.             out      21h,al
  472.             mov      al,ah
  473.             out      0a1h,al
  474.             popf
  475.             mov      [initialization],01h    ; We MUST deinit now...
  476.             mov      dx,[mixer]              ; Activate the GUS!
  477.             mov      al,09h
  478.             out      dx,al
  479.             mov      dx,[gf1_page]           ; Select voice 0
  480.             mov      al,0
  481.             out      dx,al
  482.             mov      [voice],0
  483.  
  484.             mov      ax,0
  485.             jmp      init_done
  486. bad_irq: mov      ax,2
  487.             jmp      init_done
  488. bad_dma: mov      ax,3
  489.             jmp      init_done
  490. bad_dram: mov     ax,5
  491.             jmp      init_done
  492. init_done:
  493.             pop      es
  494.             ret
  495. endp     init_gus
  496.  
  497. proc     deinit_gus  near
  498.             pushf
  499.             cli
  500.             cmp      [initialization],01h    ; Did we initialize?
  501.             jnz      no_init
  502.             mov      ah,25h
  503.             mov      al,[gf1_irq]
  504.             add      al,8
  505.             push     ds
  506.             lds      dx,[dword old_ISR1]
  507.             int      21h
  508.             pop      ds
  509.             mov      ah,25h
  510.             mov      al,[midi_irq]
  511.             add      al,8
  512.             push     ds
  513.             lds      dx,[dword old_ISR2]
  514.             int      21h
  515.             pop      ds
  516.             mov      ax,[old_flags]
  517.             out      21h,al
  518.             mov      al,ah
  519.             out      0a1h,al
  520. no_init: mov      dx,[mixer]
  521.             mov      al,0bh
  522.             out      dx,al
  523.             popf
  524.             ret
  525. endp     deinit_gus
  526.  
  527. proc     dma_status  near
  528.             xor      ax,ax
  529.             mov      al,[dma_busy]
  530.             ret
  531. endp     dma_status
  532.  
  533. proc     midi_ISR far                     ; Null ISR
  534.             push     ax
  535.             mov      al,20h
  536.             out      20h,al
  537.             pop      ax
  538.             iret
  539. endp     midi_ISR
  540.  
  541. proc     set_active  near
  542.             push     dx
  543.             dec      ax
  544.             cmp      al,13
  545.             jnc      nl13
  546.             mov      al,13
  547. nl13:    cmp      al,32
  548.             jc       lt32
  549.             mov      al,31
  550. lt32:    mov      [max_voices],al
  551.             or       al,0c0h
  552.             mov      ah,al
  553.             mov      al,0eh
  554.             call     write_8bit_reg
  555.             xor      bx,bx
  556.             mov      bl,[max_voices]
  557.             inc      bx
  558.             mov      ax,6bb8h
  559.             mov      dx,9
  560.             div      bx
  561.             mov      [divisor],ax
  562.             pop      dx
  563.             ret
  564. endp     set_active
  565.  
  566. proc     download_sound near  ; es:si = source   di = dram addr
  567.                                         ; dx:ax = size     cl = wait toggle
  568.             cmp      [dma_busy],1
  569.             jz       no_dma
  570.             mov      [dma_wait],cl
  571.             mov      [dma_size_high],dl
  572.             mov      [dma_size_low],ax
  573.             mov      [dram_addr],di
  574.             mov      ax,es
  575.             rol      ax,4
  576.             and      ax,15
  577.             mov      [dma_pos_high],al
  578.             mov      ax,es
  579.             and      ax,0fffh
  580.             rol      ax,4
  581.             and      si,0ff00h
  582.             add      ax,si
  583.             mov      [dma_pos_low],ax
  584.             xor      ax,ax
  585.             sub      ax,[dma_pos_low]
  586.             mov      [dma_send],ax
  587.             cmp      [dma_size_high],0
  588.             jnz      gt64k
  589.             mov      bx,[dma_size_low]
  590.             cmp      ax,bx
  591.             jc       gt64k
  592.             mov      [dma_send],bx
  593.             mov      [dma_size_low],0
  594.             jmp      go_dma
  595. gt64k:   sub      [dma_size_low],ax
  596.             sbb      [dma_size_high],0
  597. go_dma:  xor      ax,ax
  598.             mov      al,[play_back_dma]
  599.             mov      bx,7
  600.             imul     bx
  601.             add      ax,offset dma_channels
  602.             mov      si,ax
  603.             xor      dx,dx
  604.             mov      dl,[si]
  605.             mov      al,[play_back_dma_mask]
  606.             or       al,4
  607.             out      dx,al
  608.             mov      al,0
  609.             mov      dl,[si+1]
  610.             out      dx,al
  611.             mov      ax,[dma_pos_low]
  612.             mov      dl,[si+2]
  613.             out      dx,al
  614.             mov      al,ah
  615.             out      dx,al
  616.             mov      ax,[dma_send]
  617.             dec      ax
  618.             mov      dl,[si+3]
  619.             out      dx,al
  620.             mov      al,ah
  621.             out      dx,al
  622.             mov      al,[play_back_dma_mask]
  623.             or       al,48h
  624.             mov      dl,[si+4]
  625.             out      dx,al
  626.             mov      al,[dma_pos_high]
  627.             mov      dl,[si+5]
  628.             out      dx,al
  629.             mov      al,[play_back_dma_mask]
  630.             mov      dl,[si+6]
  631.             out      dx,al
  632.             pushf
  633.             cli
  634.             mov      al,42h
  635.             mov      cx,[dram_addr]
  636.             call     write_16bit_reg
  637.             mov      dx,[gf1_register]
  638.             mov      al,41h
  639.             out      dx,al
  640.             add      dx,2
  641.             mov      al,0a9h
  642.             mov      [dma_busy],1
  643.             out      dx,al
  644.             popf
  645.             cmp      [dma_wait],0
  646.             jz       dma_dn
  647. dma_lp1: mov      ah,6
  648.             mov      dl,0ffh
  649.             int      21h
  650.             jnz      keyht1
  651.             cmp      [dma_busy],1
  652.             jz       dma_lp1
  653.             mov      ax,0
  654. dma_dn:  ret
  655. keyht1:  mov      ax,1
  656.             jmp      dma_dn
  657. no_dma:  mov      ax,2
  658.             jmp      dma_dn
  659. endp     download_sound
  660.  
  661. proc     gf1_ISR  far                     ; Handles ALL GF1 interrupts
  662.             push     ax dx ds
  663.             mov      ax,gus_data
  664.             mov      ds,ax
  665.             call     delay
  666.             call     delay
  667. irq_lp1: mov      dx,[irq_status]
  668.             in       al,dx
  669.             cmp      al,0
  670.             jz       gf1_dn
  671.             test     al,80h
  672.             jz       no_dma2
  673.             mov      dx,[gf1_register]
  674.             mov      al,41h
  675.             out      dx,al
  676.             add      dx,2
  677.             in       al,dx
  678.             inc      [dma_pos_high]
  679.             mov      [dma_pos_low],0
  680.             cmp      [dma_send],0
  681.             jnz      lt64k
  682.             add      [dram_addr],1000h
  683.             dec      [dma_size_high]
  684.             jmp      dma_go
  685. lt64k:   mov      ax,[dma_send]
  686.             mov      cl,4
  687.             shr      ax,cl
  688.             add      [dram_addr],ax
  689. dma_go:  cmp      [dma_size_high],0
  690.             jz       lt64k2
  691.             mov      [dma_send],0
  692.             jmp      dma_go2
  693. lt64k2:  cmp      [dma_size_low],0
  694.             jz       dma_dn2
  695.             mov      ax,[dma_size_low]
  696.             mov      [dma_send],ax
  697. dma_go2: mov      ax,[dma_send]
  698.             sub      [dma_size_low],ax
  699.             sbb      [dma_size_high],0
  700.             xor      ax,ax
  701.             mov      al,[play_back_dma]
  702.             mov      bx,7
  703.             imul     bx
  704.             add      ax,offset dma_channels
  705.             mov      si,ax
  706.             xor      dx,dx
  707.             mov      dl,[si]
  708.             mov      al,[play_back_dma_mask]
  709.             or       al,4
  710.             out      dx,al
  711.             mov      al,0
  712.             mov      dl,[si+1]
  713.             out      dx,al
  714.             mov      ax,[dma_pos_low]
  715.             mov      dl,[si+2]
  716.             out      dx,al
  717.             mov      al,ah
  718.             out      dx,al
  719.             mov      ax,[dma_send]
  720.             dec      ax
  721.             mov      dl,[si+3]
  722.             out      dx,al
  723.             mov      al,ah
  724.             out      dx,al
  725.             mov      al,[play_back_dma_mask]
  726.             or       al,48h
  727.             mov      dl,[si+4]
  728.             out      dx,al
  729.             mov      al,[dma_pos_high]
  730.             mov      dl,[si+5]
  731.             out      dx,al
  732.             mov      al,[play_back_dma_mask]
  733.             mov      dl,[si+6]
  734.             out      dx,al
  735.             pushf
  736.             cli
  737.             mov      al,42h
  738.             mov      cx,[dram_addr]
  739.             call     write_16bit_reg
  740.             mov      dx,[gf1_register]
  741.             mov      al,41h
  742.             out      dx,al
  743.             add      dx,2
  744.             mov      al,0a9h
  745.             mov      [dma_busy],1
  746.             out      dx,al
  747.             popf
  748.             jmp      gf1_dn
  749. dma_dn2: mov      [dma_busy],0
  750.             jmp      gf1_dn
  751. no_dma2: test     al,40h               ; I'm not really sure why this code
  752.             jnz      no_voc               ; is here, or even if it really works.
  753.             mov      al,0fh               ; I've never really had a need to make
  754.             call     read_8bit_reg        ; sure the voice has stopped at any
  755.             mov      [irq_source],al      ; perticular time.  There's just times
  756.             and      al,1fh               ; when I need to know IF it's stopped.
  757.             mov      [irq_voice],al       ; At any rate, I never use an IRQ for
  758.             mov      al,[irq_source]      ; the end-of-voice, but it would come
  759.             and      al,0c0h              ; in nice for music, so I left the
  760.             cmp      al,0c0h              ; here for anyone to work with.
  761.             jz       irq_lp1
  762.             test     al,80h
  763.             jnz      no_voc
  764.             mov      al,[voice]
  765.             mov      [old_voice],al
  766.             mov      dx,[gf1_page]
  767.             out      dx,al
  768.             mov      al,0
  769.             call     read_8bit_reg
  770.             mov      [d1],al
  771.             mov      al,0dh
  772.             call     read_8bit_reg
  773.             test     [d1],4
  774.             jnz      virq_dn
  775.             test     al,4
  776.             jnz      virq_dn
  777.             mov      ax,100h
  778.             call     write_8bit_reg
  779.             mov      al,2
  780.             call     read_16bit_reg
  781.             mov      cx,ax
  782.             mov      al,0ah
  783.             call     write_16bit_reg
  784.             mov      al,3
  785.             call     read_16bit_reg
  786.             mov      cx,ax
  787.             mov      al,0bh
  788.             call     write_16bit_reg
  789. virq_dn: mov      al,[old_voice]
  790.             mov      dx,[gf1_page]
  791.             out      dx,al
  792. no_voc:  
  793.  
  794.  
  795. gf1_dn:  mov      al,20h
  796.             out      20h,al
  797.             pop      ds dx ax
  798.             iret
  799. endp     gf1_ISR
  800.  
  801. proc     set_volume  near  ; ax = value (0-4095)  cl = voice
  802.             push     dx
  803.             push     ax
  804.             mov      al,cl
  805.             mov      dx,[gf1_page]
  806.             out      dx,al
  807.             pop      ax
  808.             push     cx
  809.             mov      cl,4
  810.             shl      ax,cl
  811.             mov      cx,ax
  812.             mov      al,9
  813.             call     write_16bit_reg
  814.             pop      cx
  815.             pop      dx
  816.             ret
  817. endp     set_volume
  818.  
  819. proc     set_freq    near  ; ax = frequency of voice (0-44100)  cl = voice
  820.             push     dx
  821.             push     cx
  822.             push     ax
  823.             mov      al,cl
  824.             mov      dx,[gf1_page]
  825.             out      dx,al
  826.             pop      ax
  827.             mov      bx,512
  828.             imul     bx
  829.             mov      bx,[divisor]
  830.             shr      bx,1
  831.             add      ax,bx
  832.             adc      dx,0
  833.             mov      bx,[divisor]
  834.             div      bx
  835.             shl      ax,1
  836.             mov      cx,ax
  837.             mov      al,1
  838.             call     write_16bit_reg
  839.             pop      cx
  840.             pop      dx
  841.             ret
  842. endp     set_freq
  843.  
  844. proc     set_loop    near  ; al = loop ctrl register (recommended value = 3)
  845.                                     ; cl = voice
  846.             push     dx
  847.             push     cx
  848.             mov      dx,[gf1_page]
  849.             mov      ah,al
  850.             mov      al,cl
  851.             out      dx,al
  852.             mov      al,0dh
  853.             call     write_8bit_reg
  854.             pop      cx
  855.             pop      dx
  856.             ret
  857. endp     set_loop
  858.  
  859. proc     set_start   near  ; dx:ax   cl = voice
  860.             push        cx
  861.             push        dx
  862.             push        ax
  863.             mov         dx,[gf1_page]
  864.             mov         al,cl
  865.             out         dx,al
  866.             pop         ax
  867.             pop         dx
  868.             call        adjust
  869.             mov         cx,ax
  870.             mov         al,3
  871.             call        write_16bit_reg
  872.             mov         al,0bh
  873.             call        write_16bit_reg
  874.             mov         cx,dx
  875.             mov         al,2
  876.             call        write_16bit_reg
  877.             mov         al,0ah
  878.             call        write_16bit_reg
  879.             pop         cx
  880.             ret
  881. endp     set_start
  882.  
  883. proc     set_end     near  ; dx:ax   cl = voice
  884.             push        cx
  885.             push        dx
  886.             push        ax
  887.             mov         dx,[gf1_page]
  888.             mov         al,cl
  889.             out         dx,al
  890.             pop         ax
  891.             pop         dx
  892.             call        adjust
  893.             mov         cx,ax
  894.             mov         al,5
  895.             call        write_16bit_reg
  896.             mov         cx,dx
  897.             mov         al,4
  898.             call        write_16bit_reg
  899.             pop         cx
  900.             ret
  901. endp     set_end
  902.  
  903. proc     adjust      near
  904.             mov         cx,9
  905. adj_lp1: clc
  906.             rcl         ax,1
  907.             rcl         dx,1
  908.             loop        adj_lp1
  909.             ret
  910. endp     adjust
  911.  
  912. proc     play_voice  near  ; al = voice   ah = control register (00h = norm)
  913.             mov         bh,ah
  914.             mov         dx,[gf1_page]
  915.             out         dx,al
  916.             inc         dx
  917.             mov         al,80h
  918.             out         dx,al
  919.             add         dx,2
  920.             in          al,dx
  921.             test        al,1
  922.             jnz         voc_ok
  923.             mov         ax,300h
  924.             call        write_8bit_reg
  925.             mov         al,2
  926.             call        read_16bit_reg
  927.             mov         cx,ax
  928.             mov         al,0ah
  929.             call        write_16bit_reg
  930.             mov         al,3
  931.             call        read_16bit_reg
  932.             mov         cx,ax
  933.             mov         al,0bh
  934.             call        write_16bit_reg
  935. voc_ok:  pushf
  936.             cli
  937.             mov         dx,[gf1_register]
  938.             mov         al,0
  939.             out         dx,al
  940.             and         bh,5ch
  941.             add         dx,2
  942.             mov         al,bh
  943.             out         dx,al                ; Let the sound begin! :)
  944.             call        delay
  945.             out         dx,al
  946.             popf
  947.             ret
  948. endp     play_voice
  949.  
  950. proc     stop_voice  near  ; al = voice
  951.             mov         dx,[gf1_page]
  952.             out         dx,al
  953.             mov         ax,300h
  954.             call        write_8bit_reg
  955.             mov         al,2
  956.             call        read_16bit_reg
  957.             mov         cx,ax
  958.             mov         al,0ah
  959.             call        write_16bit_reg
  960.             mov         al,3
  961.             call        read_16bit_reg
  962.             mov         cx,ax
  963.             mov         al,0bh
  964.             call        write_16bit_reg
  965.             ret
  966. endp     stop_voice
  967.  
  968. proc     voice_status   near
  969.             mov         al,0h
  970.             call        read_8bit_reg
  971.             mov         ah,0
  972.             and         al,1
  973.             ret
  974. endp     voice_status
  975.  
  976. ends     gus
  977. end
  978.  
  979.